#include "stm8s.h"

/* LED PIN */
#define LED_GPIO_PORT GPIOD
#define LED_GPIO_PIN GPIO_PIN_4

/* LED Fn */
#define LED_ON GPIO_WriteLow(LED_GPIO_PORT, LED_GPIO_PIN)
#define LED_OFF GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PIN)
#define LED_REVERSE GPIO_WriteReverse(LED_GPIO_PORT, LED_GPIO_PIN)

/* ADC A1 A2 摇杆，A3 A4 灵敏度 */
#define ADC_GPIO_PORT GPIOD
#define ADC_GPIO_PIN_A1 GPIO_PIN_6 // AIN6
#define ADC_GPIO_PIN_A2 GPIO_PIN_2 // AIN3
#define ADC_GPIO_PIN_A3 GPIO_PIN_5 // AIN5
#define ADC_GPIO_PIN_A4 GPIO_PIN_3 // AIN4

/* ADC channel */
#define ADC_A1_CHANNEL ADC1_CHANNEL_6 // AIN6 - D6
#define ADC_A2_CHANNEL ADC1_CHANNEL_3 // AIN3 - D2
#define ADC_A3_CHANNEL ADC1_CHANNEL_5 // AIN5 - D5
#define ADC_A4_CHANNEL ADC1_CHANNEL_4 // AIN4 - D3

/* 按键 */
#define K_GPIO_PORT GPIOB
#define K_GPIO_PIN_1 GPIO_PIN_4
#define K_GPIO_PIN_2 GPIO_PIN_5

uint32_t time_no_change = 0; // 不活动时间

// 系统初始化，主频，IO，定时器
void System_Initializes(void)
{
  // 2分频 - 8M
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2);

  // GPIO初始化
  GPIO_Init(LED_GPIO_PORT, LED_GPIO_PIN, GPIO_MODE_OUT_PP_LOW_FAST); // led，推挽输出-高速-默认低电平

  GPIO_Init(ADC_GPIO_PORT, ADC_GPIO_PIN_A1, GPIO_MODE_IN_FL_NO_IT); // ADC1，浮动输入-无中断
  GPIO_Init(ADC_GPIO_PORT, ADC_GPIO_PIN_A2, GPIO_MODE_IN_FL_NO_IT); // ADC2，浮动输入-无中断
  GPIO_Init(ADC_GPIO_PORT, ADC_GPIO_PIN_A3, GPIO_MODE_IN_FL_NO_IT); // ADC3，浮动输入-无中断
  GPIO_Init(ADC_GPIO_PORT, ADC_GPIO_PIN_A4, GPIO_MODE_IN_FL_NO_IT); // ADC4，浮动输入-无中断

  // 定时器2
  TIM2_TimeBaseInit(TIM2_PRESCALER_32768, 244); // 定时器1s一个周期
  TIM2_ClearFlag(TIM2_FLAG_UPDATE);
  TIM2_Cmd(ENABLE);

  // 定时器4
  TIM4_TimeBaseInit(TIM4_PRESCALER_2, 39); // 定时器10us，8M系统频率再2分频，40个周期
  TIM4_ClearFlag(TIM4_FLAG_UPDATE);
}

// 定时器延时，10us
void TIMDelay_100us(uint16_t times)
{
  uint16_t usTimes = times * 10; // 一次100us
  TIM4_Cmd(ENABLE);              // 启动定时器
  while (usTimes--)
  {
    while (RESET == TIM4_GetFlagStatus(TIM4_FLAG_UPDATE))
      ;
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);
  }
  TIM4_Cmd(ENABLE); // 关闭定时器
}

void ADC_Init_A1(void)
{
  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC_A1_CHANNEL, ADC1_PRESSEL_FCPU_D2,
            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL6,
            DISABLE);

  ADC1_Cmd(ENABLE);
}

void ADC_Init_A2(void)
{
  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC_A2_CHANNEL, ADC1_PRESSEL_FCPU_D2,
            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL3,
            DISABLE);

  ADC1_Cmd(ENABLE);
}

void ADC_Init_A3(void)
{
  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC_A3_CHANNEL, ADC1_PRESSEL_FCPU_D2,
            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL5,
            DISABLE);

  ADC1_Cmd(ENABLE);
}

void ADC_Init_A4(void)
{
  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC_A4_CHANNEL, ADC1_PRESSEL_FCPU_D2,
            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL4,
            DISABLE);

  ADC1_Cmd(ENABLE);
}

uint8_t ADC_Read(void)
{
  uint8_t i;
  uint16_t adc_value = 0;

  for (i = 0; i < 5; i++)
  {
    while (RESET == ADC1_GetFlagStatus(ADC1_FLAG_EOC))
      ;
    ADC1_ClearFlag(ADC1_FLAG_EOC); // 等待转换完成，并清除标志
    if (i > 0)
    {
      adc_value += ADC1_GetConversionValue(); // 读取转换结果
    }
  }

  // 单次0-1023，4次累加0-4092，转换为0-15，按照四舍五入取值，3v电压下，0.1v以下为死区，2.9v以上为满量程
  uint16_t convert_value = ((adc_value * 15 + 4092 / 2) / 4092);
  // 取低位字节转为uint8_t，方便spi发送
  uint8_t ret = (uint8_t)(convert_value & 0xFF);

  return ret;
}

// 休眠
void enter_standby_mode(void)
{
  // led 高电平熄灭
  GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PIN);
  // 2.4G关断
  RF24L01_Turn_Off();

  // 禁用所有中断
  disableInterrupts();

  // 设置待机模式
  __asm("halt"); // 进入待机模式，停止CPU操作，等待外部中断唤醒
}

void main(void)
{

  System_Initializes();
  drv_spi_init();
  NRF24L01_Gpio_Init();
  NRF24L01_check();
  RF24L01_Init();
  RF24L01_Set_Mode(0); // 发送模式

  GPIO_WriteHigh(LED_GPIO_PORT, LED_GPIO_PIN);

  uint16_t inactiveTime = 0;
  uint8_t v1;
  uint8_t v2;
  uint8_t v3;
  uint8_t v4;
  uint8_t checkA3A4 = 1; // 是否更新灵敏度，进上电自动更新一次

  while (1)
  {
    ADC_Init_A1();
    TIMDelay_100us(1);
    v1 = ADC_Read();

    ADC_Init_A2();
    TIMDelay_100us(1);
    v2 = ADC_Read();

    if (checkA3A4 == 1)
    {
      ADC_Init_A3();
      TIMDelay_100us(1);
      v3 = ADC_Read();

      ADC_Init_A4();
      TIMDelay_100us(1);
      v4 = ADC_Read();

      checkA3A4 = 0;
    }

    // 四个数据拼接为一个32位
    uint32_t combined = ((uint32_t)v1 << 24) | ((uint32_t)v2 << 16) | ((uint32_t)v3 << 8) | v4;

    // 四个数据取低位，拼接为一个16位，末尾加FF作为结束标识
    // uint32_t combined = 0x00000000 | ((v1 & 0x0F) << 12) | ((v2 & 0x0F) << 8) | ((v3 & 0x0F) << 4) | (v4 & 0x0F);
    // combined |= 0xFF;

    NRF24L01_TxPacket((uint8_t *)&combined);
    TIMDelay_100us(10 * 80); // 80ms 一次

    if (SET == TIM2_GetFlagStatus(TIM2_FLAG_UPDATE))
    {
      // GPIO_WriteReverse(LED_GPIO_PORT, LED_GPIO_PIN);
      if (v1 == 7 & v2 == 7)
      {
        inactiveTime++;
        if ((inactiveTime + 10) > 60 * 10) // 最后10秒闪烁led
        {
          GPIO_WriteReverse(LED_GPIO_PORT, LED_GPIO_PIN);
        }
        if (inactiveTime > 60 * 10) // 10分钟不活动自动关闭
        {
          enter_standby_mode();
        }
      }
      else
      {
        inactiveTime = 0;
      }
      TIM2_ClearFlag(TIM2_FLAG_UPDATE);
      TIM2_Cmd(ENABLE); // 关闭定时器
    }
  }
}

#ifdef USE_FULL_ASSERT // 断言(参考官方)

void assert_failed(u8 *file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**** Copyright (C)2017 strongerHuang. All Rights Reserved **** END OF FILE ****/
